﻿Imports System.Xml
''' <summary>
''' 数据部节点类
''' </summary>
''' <remarks></remarks>
Public Class DataNode
    Inherits clsSyntaxNode
    '文件节
    Public FileList As New List(Of XmlElement)
    '文件节
    Public FileValList As New List(Of XmlElement)
    '函数节(COBOL废止)
    Public BuiltinList As New List(Of String)
    '外部程序节(COBOL废止)
    Public ExternalEntryList As New List(Of XmlElement)
    ''' <summary>
    ''' 工作数据节
    ''' </summary>
    ''' <remarks></remarks>
    Public WorkStorageList As New List(Of XmlElement)
    '''' <summary>
    '''' 存放不以1为下标的数组的名称
    ''''(变量名称，下标)
    '''' </summary>
    '''' <remarks></remarks>
    Public UnderBoundNotFrom1 As New Dictionary(Of String, Integer)
    ''' <summary>
    ''' 工作变量
    ''' </summary>
    ''' <remarks></remarks>
    Public WorkList As New List(Of XmlElement)
    ''' <summary>
    ''' 工作变量
    ''' </summary>
    ''' <remarks></remarks>
    Public MsgList As New List(Of XmlElement)
    ''' <summary>
    ''' 循环变量列表
    ''' </summary>
    ''' <remarks></remarks>
    Public CntList As New List(Of Integer)
    ''' <summary>
    ''' 接口变量
    ''' </summary>
    ''' <remarks></remarks>
    Public LinkageList As New List(Of XmlElement)
    ''' <summary>
    ''' 初始化列表
    ''' </summary>
    ''' <remarks>
    ''' 写在DCL块里面的动作语句
    ''' </remarks>
    Public ActionList As New clsStatementBlock
    ''' <summary>
    ''' PL1 2 COBOL
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Convert2Cobol() As List(Of String)
        Dim strCobol As New List(Of String)
        strCobol.Add("       DATA                            DIVISION.")
        '文件节  【参考文档:数据部-FILE】
        If FileList.Count > 0 Then
            strCobol.Add("       FILE                            SECTION.")
            For Each XmlFile As XmlElement In FileList
                'SYSPRINT，PRINT型的，可以不定义
                If Not (XmlFile.GetAttribute("ISPRINT") = "True" And XmlFile.GetAttribute("FILENAME") = "SYSPRINT") Then
                    For Each CommentXML As XmlElement In XmlFile.ChildNodes
                        strCobol.Add(FormatCOBOLComment(CommentXML.GetAttribute("TEXT")))
                    Next
                    If XmlFile.GetAttribute("COMMENT") <> String.Empty Then
                        strCobol.Add(Space(6) & Mid(XmlFile.GetAttribute("COMMENT"), 2, XmlFile.GetAttribute("COMMENT").Length - 2))
                    End If
                    strCobol.Add("       FD  " & XmlFile.GetAttribute("FILENAME"))
                    Dim LayOutLength As Integer = 0
                    Dim mFileInfo As CommonMethod.FileInfoRec = clsFileInfoList.GetFileInfoByName(XmlFile.GetAttribute("FILENAME"))
                    If mFileInfo.FileID = String.Empty Then
                        strCobol.Add("      *ERROR:FILE NOT FOUND IN FILELIST")
                        LogWriter.WriteLine("*ERROR:FILE NOT FOUND IN FILELIST")
                        LogWriter.WriteLine("FILENAME:" & XmlFile.GetAttribute("FILENAME"))
                    End If
                    If XmlFile.GetAttribute("FILENAME") = "SYSIN" Then
                        '如果有SYSIN文件的话，就把SYSIN当做80字符长度的文件进行处理
                        LayOutLength = 80
                    Else
                        If mFileInfo.FileID = String.Empty Then
                            LayOutLength = 0
                        Else
                            LayOutLength = mFileInfo.Length
                        End If
                    End If
                    strCobol.Add("       BLOCK  CONTAINS   0 RECORDS")
                    strCobol.Add("       LABEL RECORD    IS  STANDARD")
                    'VB-FB
                    If mFileInfo.FileID = String.Empty Then
                        strCobol.Add("       RECORD CONTAINS  " & Mid(LayOutLength.ToString & Space(5), 1, 5) & " CHARACTERS")
                        strCobol.Add("       RECORDING MODE  IS  F.")
                    Else
                        If mFileInfo.RECFM = enmRECFM.FB Then
                            strCobol.Add("       RECORD CONTAINS  " & Mid(LayOutLength.ToString & Space(5), 1, 5) & " CHARACTERS")
                            strCobol.Add("       RECORDING MODE  IS  F.")
                        Else
                            strCobol.Add("       RECORDING MODE  IS  V.")
                            strCobol.Add("       RECORD VARYING FROM 1 TO " & mFileInfo.Length)
                            strCobol.Add("           DEPENDING ON " & mFileInfo.FileID & "-VLI.")
                        End If
                    End If
                    strCobol.Add(Mid(Space(LeftStart) & "01  " & XmlFile.GetAttribute("FILENAME") & "-REC" & Space(PICPosition), 1, PICPosition) & _
                                     "PIC  X(" & Format(LayOutLength, "0#") & ").")
                End If
            Next
        End If
        If WorkStorageList.Count > 0 Then
            strCobol.Add("       WORKING-STORAGE                 SECTION.")
            For Each mDataItem As XmlElement In WorkStorageList
                SetDataString(strCobol, mDataItem)
            Next
        End If
        '工作数据节
        If WorkList.Count > 0 Then
            strCobol.Add("      ******************************************************************")
            strCobol.Add("      **     ワーク変数　　　　　　　　　　　                          *")
            strCobol.Add("      ******************************************************************")
            For Each mDataItem As XmlElement In WorkList
                SetDataString(strCobol, mDataItem)
            Next
        End If

        '文件关联变量
        If FileValList.Count > 0 Then
            strCobol.Add("      ******************************************************************")
            strCobol.Add("      **     ファイル　ステータス　　　　　　                          *")
            strCobol.Add("      ******************************************************************")
            For Each mDataItem As XmlElement In FileValList
                SetDataString(strCobol, mDataItem)
            Next
        End If

        '如果需要MSG变量的话
        If MsgList.Count > 0 Then
            strCobol.Add("      ******************************************************************")
            strCobol.Add("      **     メッセージ変数　　　　　　　　　                          *")
            strCobol.Add("      ******************************************************************")
            strCobol.Add(Mid("       01  WK-PL1-MSG" & Space(39), 1, 39) & "PIC X(200)  VALUE  SPACE.")
            strCobol.Add(Mid("       01  WK-PL1-MSG-LENGTH" & Space(39), 1, 39) & "PIC 9(03)  VALUE  ZERO.")
            For Each mDataItem As XmlElement In MsgList
                SetDataString(strCobol, mDataItem)
            Next
        End If
        '如果需要循环变量的话
        If CntList.Count > 0 Then
            strCobol.Add("      ******************************************************************")
            strCobol.Add("      **     ループ変数　　　　　　　　　　　                          *")
            strCobol.Add("      ******************************************************************")
            CntList.Sort()
            '无法确定长度的公用循环变量
            strCobol.Add("       01  CNT-PLI-COMMON  PIC S9(9)  COMP-3  VALUE  ZERO.")
            For i As Byte = 0 To CntList.Count - 1
                strCobol.Add(Mid("       01  CNT-PL1-" & CntList(i) & Space(39), 1, 39) & "PIC S9(9)  COMP-3  VALUE  ZERO.")
            Next
        End If
        '如果需要Linkage
        If LinkageList.Count > 0 Then
            strCobol.Add("       LINKAGE                                     SECTION.")
            For Each mDate As XmlElement In LinkageList
                SetDataString(strCobol, mDate)
            Next
        End If
        Return strCobol
    End Function
    ''' <summary>
    ''' 设置数据字符 
    ''' </summary>
    ''' <param name="strDataDefine"></param>
    ''' <param name="mDate"></param>
    ''' <remarks></remarks>
    Private Sub SetDataString(ByVal strDataDefine As List(Of String), ByVal mDate As XmlElement)
        Dim strLastLine As String = String.Empty
        '树结构的整段代码代码，移到树的前面
        If mDate.ChildNodes.Count > 0 Then
            For Each mNode As XmlElement In mDate.ChildNodes
                If mNode.Name = "COMMENTLIST" Then
                    strDataDefine.Add(FormatCOBOLComment(mNode.GetAttribute("TEXT")))
                End If
            Next
        End If
        Select Case mDate.Name
            Case "COMMENTLIST"
                strDataDefine.Add(FormatCOBOLComment(mDate.GetAttribute("TEXT")))
            Case "SINGLEDATA"
                '对于FILE定义和ENTRY定义等，不输出
                If mDate.GetAttribute("TYPE") <> "NA" Then
                    For Each Str As String In clsDataConverter.GetDataDefine(mDate)
                        strDataDefine.Add(Str)
                    Next
                    strLastLine = strDataDefine(strDataDefine.Count - 1)
                    strDataDefine(strDataDefine.Count - 1) = strLastLine
                End If
            Case "TREEDATA"
                For Each Str As String In clsDataConverter.GetDataDefine(mDate)
                    strDataDefine.Add(Str)
                Next
                If mDate.ChildNodes.Count > 0 Then
                    GetSubTree(strDataDefine, mDate)
                End If
                strLastLine = strDataDefine(strDataDefine.Count - 1)
                strDataDefine(strDataDefine.Count - 1) = strLastLine
            Case "INCLUDE"
                Dim copyBook As String = mDate.GetAttribute("COPYBOOKNAME")
                '防止数据部里的废止COPY句
                If clsCopyBookList.GetCopyBookInfoByName(copyBook).IsDisposed = False Then
                    For Each Str As String In clsDataConverter.GetDataDefine(mDate)
                        strDataDefine.Add(Str)
                    Next
                    strLastLine = strDataDefine(strDataDefine.Count - 1)
                    strDataDefine(strDataDefine.Count - 1) = strLastLine
                End If
            Case "MACRO"
                '@JRI  PROC 特殊处理 开始
                'JRI专用初始化宏
                strDataDefine.Add(Space(LeftStart) & (mDate.GetAttribute("COMMAND")))
                '@JRI  PROC 特殊处理 完了
        End Select
    End Sub
    ''' <summary>
    ''' 获得树结构COBOL代码
    ''' </summary>
    ''' <param name="mStrList"></param>
    ''' <param name="xmlParent"></param>
    ''' <remarks></remarks>
    Private Sub GetSubTree(ByVal mStrList As List(Of String), ByVal xmlParent As XmlElement)
        For Each mChild As XmlElement In xmlParent
            If Not (mChild.Name = "COMMENTLIST") Then
                If mChild.ChildNodes.Count > 0 Then
                    For Each mNode As XmlElement In mChild.ChildNodes
                        If mNode.Name = "COMMENTLIST" Then
                            mStrList.Add(FormatCOBOLComment(mNode.GetAttribute("TEXT")))
                        End If
                    Next
                End If
                For Each Str As String In clsDataConverter.GetDataDefine(mChild)
                    mStrList.Add(Str)
                Next
                If mChild.ChildNodes.Count > 0 Then
                    GetSubTree(mStrList, mChild)
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' 获得XML结构
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetXMLElement() As System.Xml.XmlElement
        Dim mRootElement As XmlElement
        mRootElement = mXmlDocument.CreateElement("DATA")
        'File
        Dim mFileSectionElement As XmlElement
        mFileSectionElement = mXmlDocument.CreateElement("FILESECTION")
        For Each mFileNode As XmlNode In FileList
            mFileSectionElement.AppendChild(mFileNode)
        Next
        mRootElement.AppendChild(mFileSectionElement)
        'Builtin
        Dim mBulitinElement As XmlElement
        mBulitinElement = mXmlDocument.CreateElement("BUILTIN")
        For Each mBUILTIN As String In BuiltinList
            Dim mXmlElement As XmlElement
            mXmlElement = mXmlDocument.CreateElement(mBUILTIN)
            mBulitinElement.AppendChild(mXmlElement)
        Next
        mRootElement.AppendChild(mBulitinElement)
        'ExternalEntry
        Dim mExternalEntryElement As XmlElement
        mExternalEntryElement = mXmlDocument.CreateElement("EXTERNALENTRYLIST")
        For Each mExternalEntry As XmlElement In ExternalEntryList
            mExternalEntryElement.AppendChild(mExternalEntry)
        Next
        mRootElement.AppendChild(mExternalEntryElement)

        'Data-注意：BASED（Point）的数据放在LINKAGE里面了
        Dim mWorkstageElement As XmlElement
        mWorkstageElement = mXmlDocument.CreateElement("WORKSTAGE")
        For Each mData As XmlElement In WorkStorageList
            mWorkstageElement.AppendChild(mData)
        Next
        mRootElement.AppendChild(mWorkstageElement)

        'CNT
        Dim mCNTElement As XmlElement = mXmlDocument.CreateElement("COUNT")
        If CntList.Count > 0 Then
            CntList.Sort()
            For i As Byte = 0 To CntList.Count - 1
                Dim wkCountXml As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
                wkCountXml.SetAttribute("NAME", "CNT-PL1-" & CntList(i))
                wkCountXml.SetAttribute("TYPE", "PIC")
                wkCountXml.SetAttribute("PIC", "S9")
                wkCountXml.SetAttribute("LayNo", "1")
                wkCountXml.SetAttribute("REPEAT", "1")
                mCNTElement.AppendChild(wkCountXml)
            Next
        End If
        mRootElement.AppendChild(mCNTElement)

        'WorkTemp
        Dim mTempElement As XmlElement
        mTempElement = mXmlDocument.CreateElement("TEMP")
        For Each mData As XmlElement In WorkList
            mTempElement.AppendChild(mData)
        Next
        mRootElement.AppendChild(mTempElement)

        'Msg
        Dim mMsgElement As XmlElement
        mMsgElement = mXmlDocument.CreateElement("MSGLIST")
        For Each mData As XmlElement In MsgList
            mMsgElement.AppendChild(mData)
        Next
        mRootElement.AppendChild(mMsgElement)


        'Linkage
        Dim mLinkageDataElement As XmlElement
        mLinkageDataElement = mXmlDocument.CreateElement("LINKAGE")
        For Each mData As XmlElement In LinkageList
            mLinkageDataElement.AppendChild(mData)
        Next
        mRootElement.AppendChild(mLinkageDataElement)

        'InitData
        Dim mInitDataElement As XmlElement
        mInitDataElement = mXmlDocument.CreateElement("INITDATA")
        mInitDataElement.AppendChild(ActionList.GetXMLElement)
        mRootElement.AppendChild(mInitDataElement)
        Return mRootElement
    End Function
    ''' <summary>
    ''' 添加数据定义
    ''' </summary>
    ''' <param name="DataNode"></param>
    ''' <remarks></remarks>
    Public Sub AddData(ByVal DataNode As System.Xml.XmlElement)
        Select Case DataNode.Name
            Case "SINGLEDATA"
                Select Case DataNode.GetAttribute("TYPE")
                    Case "BUILTINDEFINE"
                        '内部函数
                        BuiltinList.Add(DataNode.GetAttribute("NAME"))
                    Case "FILEDEFINE"
                        FileList.Add(DataNode)
                        If Not (DataNode.GetAttribute("ISPRINT") = "True" And DataNode.GetAttribute("FILENAME") = "SYSPRINT") Then
                            If MyConfig.IsCreateFileStatus Then
                                '如果需要文件状态变量的话
                                Dim FileStatesNode As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
                                With FileStatesNode
                                    .SetAttribute("NAME", DataNode.GetAttribute("FILENAME") & "_ST")
                                    .SetAttribute("TYPE", "CHAR")
                                    .SetAttribute("LENGTH", 2)
                                    .SetAttribute("LayNo", 1)
                                    .SetAttribute("INIT", "SPACES")
                                End With
                                FileValList.Add(FileStatesNode)
                            End If
                            Dim mFileInfo As CommonMethod.FileInfoRec = clsFileInfoList.GetFileInfoByName(DataNode.GetAttribute("FILENAME"))
                            If mFileInfo.FileID <> String.Empty Then
                                If mFileInfo.RECFM = enmRECFM.VB Then
                                    Dim FileLengthNode As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
                                    With FileLengthNode
                                        .SetAttribute("NAME", DataNode.GetAttribute("FILENAME") & "_LVI")
                                        .SetAttribute("TYPE", "FIXED BIN")
                                        '必须为无符号整数
                                        .SetAttribute("SIGNED", "FALSE")
                                        .SetAttribute("LENGTH", 15)
                                        .SetAttribute("LayNo", 1)
                                    End With
                                    FileValList.Add(FileLengthNode)
                                End If
                            End If
                        End If
                        mEnvironmentNode.AddFile(DataNode)
                    Case "ENTRYDEFINE"
                        Dim EntryXml As XmlElement = mXmlDocument.CreateElement("EXTERNALENTRY")
                        EntryXml.SetAttribute("NAME", DataNode.GetAttribute("NAME"))
                        ExternalEntryList.Add(EntryXml)
                    Case Else
                        WorkStorageList.Add(DataNode)
                End Select
            Case "TREEDATA"
                WorkStorageList.Add(DataNode)
            Case "MultiSingleData"
                For Each SubDataNode In DataNode.ChildNodes
                    AddData(SubDataNode.Clone)
                Next
            Case Else
                WorkStorageList.Add(DataNode)
        End Select
    End Sub
    ''' <summary>
    ''' 添加初始化操作(单条)
    ''' </summary>
    ''' <param name="SyntaxNode"></param>
    ''' <remarks></remarks>
    Public Sub AddSingleInit(ByVal SyntaxNode As System.Xml.XmlElement)
        ActionList.SingleStatementList.Add(SyntaxNode)
    End Sub
    ''' <summary>
    ''' 添加初始化操作(块)
    ''' </summary>
    ''' <param name="SyntaxNode"></param>
    ''' <remarks></remarks>
    Public Sub AddBlockInit(ByVal SyntaxNode As clsSyntaxNode)
        ActionList.BlockOprList.Add(SyntaxNode)
    End Sub
End Class


